﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="GenericConverter.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   The generic converter.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Collaboris.DataAccess
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// The generic converter.
    /// </summary>
    /// <typeparam name="K">
    /// </typeparam>
    /// <typeparam name="V">
    /// </typeparam>
    public class GenericConverter<K, V>
    {
        #region Constants and Fields

        /// <summary>
        /// The key to value dictionary.
        /// </summary>
        private Dictionary<K, V> keyToValueDictionary;

        /// <summary>
        /// The value to key dictionary.
        /// </summary>
        private Dictionary<V, K> valueToKeyDictionary;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="GenericConverter{K,V}"/> class. 
        /// Initializes a new instance of the <see cref="T:System.Object"/> class.
        /// </summary>
        /// <param name="translationDictionary">
        /// The translation Dictionary.
        /// </param>
        public GenericConverter(Dictionary<K, V> translationDictionary)
        {
            this.keyToValueDictionary = translationDictionary;

            foreach (K key in this.KeyToValueDictionary.Keys)
            {
                this.ValueToKeyDictionary.Add(this.KeyToValueDictionary[key], key);
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="GenericConverter{K,V}"/> class.
        /// </summary>
        public GenericConverter()
        {
        }

        #endregion

        #region Properties

        /// <summary>
        /// The key to value dictionary.
        /// </summary>
        private Dictionary<K, V> KeyToValueDictionary
        {
            get
            {
                if (this.keyToValueDictionary == null)
                {
                    this.keyToValueDictionary = new Dictionary<K, V>();
                }

                return this.keyToValueDictionary;
            }
        }

        /// <summary>
        /// The value to key dictionary.
        /// </summary>
        private Dictionary<V, K> ValueToKeyDictionary
        {
            get
            {
                if (this.valueToKeyDictionary == null)
                {
                    this.valueToKeyDictionary = new Dictionary<V, K>();
                }

                return this.valueToKeyDictionary;
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// The add.
        /// </summary>
        /// <param name="key">
        /// The key.
        /// </param>
        /// <param name="value">
        /// The value.
        /// </param>
        public void Add(K key, V value)
        {
            this.ValueToKeyDictionary.Add(value, key);
            this.KeyToValueDictionary.Add(key, value);
        }

        /// <summary>
        /// The convert.
        /// </summary>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <returns>
        /// </returns>
        /// <exception cref="InvalidCastException">
        /// </exception>
        public K Convert(V value)
        {
            if (this.ValueToKeyDictionary == null)
            {
                throw new NullReferenceException("Translationdictionaries have not been initialised");
            }

            if (!this.ValueToKeyDictionary.Keys.Contains(value))
            {
                throw new InvalidCastException(String.Format("Cannot convert '{0}' into '{1}'", value, typeof(K)));
            }

            return this.ValueToKeyDictionary[value];
        }

        /// <summary>
        /// The convert.
        /// </summary>
        /// <param name="value">
        /// The value.
        /// </param>
        /// <returns>
        /// </returns>
        /// <exception cref="InvalidCastException">
        /// </exception>
        public V Convert(K value)
        {
            if (this.KeyToValueDictionary == null)
            {
                throw new NullReferenceException("Translationdictionaries have not been initialised");
            }

            if (!this.KeyToValueDictionary.Keys.Contains(value))
            {
                throw new InvalidCastException(String.Format("Cannot convert '{0}' into '{1}'", value, typeof(K)));
            }

            return this.KeyToValueDictionary[value];
        }

        #endregion
    }
}